package com.socket.nio.nio.chat.example.handler;

import com.socket.nio.nio.chat.example.protocol.ChatMessage;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Hexudong
 * @date 2025/5/12
 */
@Slf4j
public class ChatServerHandler extends SimpleChannelInboundHandler<ChatMessage.Msg> {
  private static final ConcurrentHashMap<String, Channel> users = new ConcurrentHashMap<>();
  private static final ConcurrentHashMap<String, Set<String>> groups = new ConcurrentHashMap<>();

  @Override
  protected void channelRead0(ChannelHandlerContext ctx, ChatMessage.Msg msg) {
    switch (msg.getType()) {
      case LOGIN:
        // 处理登录事件
        handleLogin(ctx, msg);
        break;
      case TEXT:
        // 处理消息发送事件
        handleTextMessage(msg);
        break;
      case CREATE_GROUP:
        // 处理创建群组事件
        handleCreateGroup(msg);
        break;
      case JOIN_GROUP:
        // 处理加入群组事件
        handleJoinGroup(msg);
        break;
      case GROUP_MSG:
        // 处理处理群消息事件
        handleGroupMessage(msg);
        break;
    }
  }

  private void handleLogin(ChannelHandlerContext ctx, ChatMessage.Msg msg) {
    log.info("服务端处理登录事件, 接收到消息 : {}", msg);
    String username = msg.getUsername();
    if (users.containsKey(username)) {
      sendError(ctx, "Username already exists");
      return;
    }
    users.put(username, ctx.channel());
    sendSuccess(ctx, username + " login successful");
    broadcastSystemMessage(username + " joined the chat");
    log.info("服务端处理登录事件结束");
  }

  private void handleTextMessage(ChatMessage.Msg msg) {
    log.info("服务端处理消息发送事件, 接收到消息 : {}", msg);
    Channel targetChannel = users.get(msg.getTarget());
    if (targetChannel != null) {
      targetChannel.writeAndFlush(msg);
    }
    log.info("服务端处理消息发送事件结束");
  }

  private void handleCreateGroup(ChatMessage.Msg msg) {
    log.info("服务端处理创建群组事件, 接收到消息 : {}", msg);
    String groupName = msg.getGroupName();
    if (groups.containsKey(groupName)) {
      sendError((ChannelHandlerContext) users.get(msg.getUsername()), "Group already exists");
      return;
    }
    groups.put(groupName, ConcurrentHashMap.newKeySet());
    groups.get(groupName).add(msg.getUsername());
    sendSuccess((ChannelHandlerContext) users.get(msg.getUsername()), "Group created: " + groupName);
    log.info("服务端处理创建群组事件结束");
  }

  private void handleJoinGroup(ChatMessage.Msg msg) {
    log.info("服务端处理加入群组事件, 接收到消息 : {}", msg);
    String groupName = msg.getGroupName();
    Set<String> members = groups.get(groupName);
    if (members == null) {
      sendError((ChannelHandlerContext) users.get(msg.getUsername()), "Group not exists");
      return;
    }
    members.add(msg.getUsername());
    broadcastGroupMessage(groupName, msg.getUsername() + " joined the group");
    log.info("服务端处理加入群组事件结束");
  }

  private void handleGroupMessage(ChatMessage.Msg msg) {
    log.info("服务端处理群组消息事件, 接收到消息 : {}", msg);
    Set<String> members = groups.get(msg.getGroupName());
    if (members != null) {
      members.stream()
          .map(users::get)
          .filter(Objects::nonNull)
          .forEach(channel -> channel.writeAndFlush(msg));
    }
    log.info("服务端处理群组消息事件结束");
  }

  /**
   * 发送错误消息给指定客户端
   */
  private void sendError(ChannelHandlerContext ctx, String message) {
    ctx.writeAndFlush(buildSystemMsg("ERROR: " + message));
  }

  /**
   * 发送成功响应给指定客户端
   */
  private void sendSuccess(ChannelHandlerContext ctx, String message) {
    ctx.writeAndFlush(buildSystemMsg("SUCCESS: " + message));
  }

  /**
   * 发送系统广播消息（给所有在线用户）
   */
  private void broadcastSystemMessage(String message) {
    if (users.isEmpty()) {
      return;
    }
    users.forEach((userName, channel) -> {
      if (channel.isActive()) {
        ChatMessage.Msg systemMsg = buildSystemMsg("系统通知: 尊敬的用户[" + userName + "], " + message);
        channel.writeAndFlush(systemMsg);
      }
    });
  }

  /**
   * 广播群组消息
   */
  private void broadcastGroupMessage(String groupName, String message) {
    Set<String> members = groups.get(groupName);
    if (members != null) {
      ChatMessage.Msg groupMsg = ChatMessage.Msg.newBuilder()
          .setType(ChatMessage.Msg.MsgType.GROUP_MSG)
          .setGroupName(groupName)
          .setContent(message)
          .build();

      members.stream()
          .map(users::get)
          .filter(Objects::nonNull)
          .filter(Channel::isActive)
          .forEach(channel -> channel.writeAndFlush(groupMsg));
    }
  }

  /**
   * 构建系统消息对象
   */
  private ChatMessage.Msg buildSystemMsg(String content) {
    return ChatMessage.Msg.newBuilder()
        .setType(ChatMessage.Msg.MsgType.SYSTEM)
        .setContent(content)
        .build();
  }
}
